package club.zhcs.init;

import java.util.List;
import java.util.Map;

import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.util.Daos;
import org.nutz.ioc.Ioc;
import org.nutz.json.Json;
import org.nutz.lang.ContinueLoop;
import org.nutz.lang.Each;
import org.nutz.lang.ExitLoop;
import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.LoopException;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Logs;
import org.nutz.mvc.NutConfig;
import org.nutz.mvc.Setup;

import club.zhcs.bean.auth.Permission;
import club.zhcs.bean.auth.Role;
import club.zhcs.bean.auth.RolePermission;
import club.zhcs.bean.auth.User;
import club.zhcs.bean.auth.User.Status;
import club.zhcs.bean.auth.UserRole;
import club.zhcs.dao.acl.PermissionDao;
import club.zhcs.dao.acl.RoleDao;
import club.zhcs.dao.acl.RolePermissionDao;
import club.zhcs.dao.acl.UserDao;
import club.zhcs.dao.acl.UserRoleDao;
import club.zhcs.vo.InstalledRole;

/**
 * 
 * @author 王贵源
 *
 * @email kerbores@kerbores.com
 *
 * @description 应用数据初始化
 * 
 * @copyright 内部代码,禁止转发
 *
 *
 * @time 2016年1月26日 下午3:33:52
 */
public class ZHCSSetup implements Setup {
	Dao dao;

	RoleDao roleDao;

	UserRoleDao userRoleDao;

	RolePermissionDao rolePermissionDao;

	PermissionDao permissionDao;

	Role admin;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.nutz.mvc.Setup#init(org.nutz.mvc.NutConfig)
	 */
	@Override
	public void init(NutConfig config) {
		dao = config.getIoc().get(Dao.class);
		Ioc ioc = config.getIoc();
		roleDao = ioc.get(RoleDao.class);

		userRoleDao = ioc.get(UserRoleDao.class);

		permissionDao = ioc.get(PermissionDao.class);

		rolePermissionDao = ioc.get(RolePermissionDao.class);
		Daos.createTablesInPackage(dao, "club.zhcs", false);
		Daos.createTablesInPackage(dao, "com.kerbores", false);
		initACL(config.getIoc());
	}

	/**
	 * @param ioc
	 */
	private void initACL(Ioc ioc) {

		UserDao userDao = ioc.get(UserDao.class);
		User surperMan = null;
		if ((surperMan = userDao.findByCondition(Cnd.where("name", "=", "admin"))) == null) {
			surperMan = new User();
			surperMan.setEmail("kerbores@zhcs.club");
			surperMan.setName("admin");
			surperMan.setPassword(Lang.md5("123456"));
			surperMan.setPhone("18996359755");
			surperMan.setRealName("王贵源");
			surperMan.setStatus(Status.ACTIVED);
			surperMan = userDao.save(surperMan);
		}

		// 角色数据

		admin = roleDao.findByCondition(Cnd.where("name", "=", InstalledRole.ADMIN.getName()));
		if (admin == null) {
			admin = roleDao.save(InstalledRole.ADMIN.toRole());
		}

		// 超级管理员
		if (userRoleDao.findByCondition(Cnd.where("userId", "=", surperMan.getId()).and("roleId", "=", admin.getId())) == null) {
			UserRole ur = new UserRole();
			ur.setRoleId(admin.getId());
			ur.setUserId(surperMan.getId());
			ur.setType(surperMan.getUserType());
			userRoleDao.save(ur);
		}

		String info = Files.read("menu.js");
		List<Map> list = (List) Json.fromJson(info);
		dao.create(Permission.class, true);
		Lang.each(list, new Each<Map>() {

			@Override
			public void invoke(int index, Map map, int length) throws ExitLoop, ContinueLoop, LoopException {
				NutMap data = NutMap.WRAP(map);
				save(data, null);
			}
		});

	}

	/**
	 * 
	 * @param data
	 * @param pName
	 *
	 * @author 王贵源
	 */
	protected void save(NutMap data, String pName) {
		if (hasSub(data)) {
			final Permission p = Lang.map2Object(data, Permission.class);
			p.setNeedPermission(pName);
			p.setInstalled(true);
			if (!permissionDao.has("name", p.getName())) {
				dao.insert(p);
				RolePermission rp = rolePermissionDao.findByCondition(Cnd.where("roleId", "=", admin.getId()).and("permissionId", "=", p.getId()));
				if (rp == null) {
					// 为admin授权
					rp = new RolePermission();
					rp.setPermissionId(p.getId());
					rp.setRoleId(admin.getId());
					rolePermissionDao.save(rp);
				}
			}
			// 获取 sub 迭代 递归
			Lang.each(data.getList("sub", NutMap.class), new Each<NutMap>() {

				@Override
				public void invoke(int index, NutMap ele, int length) throws ExitLoop, ContinueLoop, LoopException {
					save(ele, p.getName());
				}
			});

		} else {
			Permission p = Lang.map2Object(data, Permission.class);
			p.setNeedPermission(pName);
			p.setInstalled(true);
			if (!permissionDao.has("name", p.getName())) {
				dao.insert(p);
				RolePermission rp = rolePermissionDao.findByCondition(Cnd.where("roleId", "=", admin.getId()).and("permissionId", "=", p.getId()));
				if (rp == null) {
					// 为admin授权
					rp = new RolePermission();
					rp.setPermissionId(p.getId());
					rp.setRoleId(admin.getId());
					rolePermissionDao.save(rp);
				}
			}
		}
	}

	/**
	 * 
	 * @param data
	 * @return
	 *
	 * @author 王贵源
	 */
	protected boolean hasSub(NutMap data) {
		return data.get("sub") != null && !data.getList("sub", Object.class).isEmpty();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.nutz.mvc.Setup#destroy(org.nutz.mvc.NutConfig)
	 */
	@Override
	public void destroy(NutConfig nc) {
		Logs.get().debug("shutdown!!");
	}

}
